﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using l1cs.server.model.Instance;
using l1cs.server.serverpackets;
using l1cs.server.model.skill;
using l1cs.server.model;
using l1cs.server.model.trap;

namespace l1cs.server.clientpackets
{
    public class C_MoveChar : ClientBasePacket
    {
        private static Logger _log = Logger.getLogger( typeof( C_MoveChar ).FullName );

        private static SByte[] HEADING_TABLE_X = { 0, 1, 1, 1, 0, -1, -1, -1 };
        private static SByte[] HEADING_TABLE_Y = { -1, -1, 0, 1, 1, 1, 0, -1 };
        private static int CLIENT_LANGUAGE = Config.CLIENT_LANGUAGE;

        // マップタイル調査用
        private void sendMapTileLog( L1PcInstance pc )
        {
            pc.sendPackets( new S_SystemMessage( pc.getMap().toString(
                    pc.getLocation() ) ) );
        }

        // 移動
        public C_MoveChar( byte[] decrypt, ClientThread client )
            : base( decrypt )
        {

            int locx = readH();
            int locy = readH();
            int heading = readC();

            L1PcInstance pc = client.getActiveChar();

            if ( pc.isTeleport() )
            { // テレポート処理中
                return;
            }

            // 移動要求間隔をチェックする
            if ( Config.CHECK_MOVE_INTERVAL )
            {
                // TODO 優先度9 移動速度チェック
                //int result;
                //result = pc.getAcceleratorChecker().checkInterval( AcceleratorChecker.ACT_TYPE.MOVE );
                //if ( result == AcceleratorChecker.R_DISCONNECTED )
                //{
                //    return;
                //}
            }

            pc.killSkillEffectTimer( L1SkillId.MEDITATION );
            pc.setCallClanId( 0 ); // コールクランを唱えた後に移動すると召喚無効

            if ( !pc.hasSkillEffect( L1SkillId.ABSOLUTE_BARRIER ) )
            { // アブソルートバリア中ではない
                pc.setRegenState( L1PcInstance.REGENSTATE_MOVE );
            }
            pc.getMap().setPassable( pc.getLocation(), true );

            if ( CLIENT_LANGUAGE == 3 )
            { // Taiwan Only
                heading ^= 0x49;
                locx = pc.getX();
                locy = pc.getY();
            }

            locx += HEADING_TABLE_X[heading];
            locy += HEADING_TABLE_Y[heading];

            if ( Dungeon.getInstance().dg( locx, locy, pc.getMap().getId(), pc ) )
            { // ダンジョンにテレポートした場合
                return;
            }
            if ( DungeonRandom.getInstance().dg( locx, locy, pc.getMap().getId(), pc ) )
            { // テレポート先がランダムなテレポート地点
                return;
            }

            pc.getLocation().set( locx, locy );
            pc.setHeading( heading );
            if ( pc.isGmInvis() || pc.isGhost() )
            {
            }
            else if ( pc.isInvisble() )
            {
                pc.broadcastPacketForFindInvis( new S_MoveCharPacket( pc ), true );
            }
            else
            {
                pc.broadcastPacket( new S_MoveCharPacket( pc ) );
            }

            // sendMapTileLog(pc); // 移動先タイルの情報を送る(マップ調査用)

            L1WorldTraps.getInstance().onPlayerMoved( pc );

            pc.getMap().setPassable( pc.getLocation(), false );
            // user.UpdateObject(); // 可視範囲内の全オブジェクト更新
        }
    }
}